from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys,os,requests,json

from widgetUsb import UsbPort,UsbRead
from widgetComInterface import *
from widgetCom import *
from widgetEs import ElasticSearch
from widgetProtocol import ProtocolSelectWidget
from widgetMenuBar import MenuBarWidget
from widgetMessage import msgDialog
from forwarServer import ForwardServer
from config import config
from log import logger
import traceback

rootPath = os.path.abspath(os.path.curdir)
logger.info(rootPath)
sys.path.append(rootPath)


class MainWin(QMainWindow):

    def __init__(self):
        super().__init__()


        # 串口group
        self.serial = SerialPortWidget("485")
        self.groupSerial = QGroupBox("串口")
        layoutSerial = QVBoxLayout()
        layoutSerial.addWidget(self.serial)
        self.groupSerial.setLayout(layoutSerial)

        # 网口
        self.tcpClient = TcpClientWidget("Tcp")
        self.groupTcp = QGroupBox("TCP")
        layoutTcp = QVBoxLayout()
        layoutTcp.addWidget(self.tcpClient)
        self.groupTcp.setLayout(layoutTcp)

        # Usb group
        self.usb = UsbPort(config.get("vid"), config.get("pid"))
        self.groupUsb = QGroupBox("USB")
        layoutUsb = QVBoxLayout()
        layoutUsb.addWidget(self.usb)
        self.groupUsb.setLayout(layoutUsb)

        # 左侧控件添加
        self.layoutLeft = QVBoxLayout()
        self.groupSerial.setMaximumWidth(250)
        self.groupTcp.setMaximumWidth(250)
        self.groupUsb.setMaximumWidth(250)
        self.layoutLeft.addWidget(self.groupSerial)
        self.layoutLeft.addWidget(self.groupTcp)
        self.layoutLeft.addWidget(self.groupUsb)
        # 创建一个空控件, 把串口和usb顶上去
        # widgetReserve = QWidget()
        # widgetReserve.setMinimumHeight(800)
        # self.layoutLeft.addWidget(widgetReserve)
        self.layoutLeft.addStretch()


        # 右侧控件
        self.tabBar = QTabWidget()
        self.es = ElasticSearch(self.usb, config)
        self.comWdiget = ComBaseWidget()
        self.tabBar.addTab(self.comWdiget, "通讯")
        self.tabBar.addTab(self.es, "日志上传")

        layoutMain = QHBoxLayout()
        layoutMain.addLayout(self.layoutLeft)
        layoutMain.addWidget(self.tabBar)

        self.centerWidget = QWidget()
        self.centerWidget.setLayout(layoutMain)

        self.setCentralWidget(self.centerWidget)
        self.setGeometry(100,100,1560,768)
        self.setWindowTitle("通讯调试工具 ver2.2.2")
        
        self.mb = MenuBarWidget()
        self.setMenuBar(self.mb)

        self.mb.actionSaveLog.triggered.connect(self.savelog2Local)
        self.mb.actionClearLog.triggered.connect(self.comWdiget.logClear)

        self.server = ForwardServer()
        self.server.start()

        # 1.0   正式发布版本
        # 1.1   * 修复升级时, 文件大小为整数时的崩溃问题
        #       * 功能: ecat导出可用于flash烧写的文件
        # 1.2   * 修复crc的bug
        # 1.3   * 修复手动退出升级时, 退出的bug
        # 1.4   * 修复解析错误的问题, 以发送的最后一条为目标解析
        #       * 脚本时间单位修改为ms
        # 2.0   * 修改为DLL加载方式
        #       * 脚本升级, 升级合并到脚本当中  
        # 2.1   * DLL的analyse解析为字符串
        #       * 脚本目标功能添加
        # 2.1.1 * 修复定时发送, 设备列表不能递增的问题
        # 2.1.2 * 1. 修复定时器发送时, 不提前检查错误引起的多次报错问题
        #       * 2. 当使用定时器功能且设列表不为空时, 发送到最后一个自动停止
        #       * 3. 命令记忆, 在点击发送后保存
        # 2.1.4 * 1. 修复脚本的循环执行不生效的问题
        #       * 2. 修复脚本retry没有执行delay导致的失败问题
        # 2.1.5 * 1. 修复脚本执行后, 命令切换卡顿的问题
        #       * 2. 修复相同命令多配置的情况下因命令缓存导致的多配置相同的问题
        # 2.2.0 # 使用python3.7.9打包, 兼容win7
        # 2.2.1 # 1. 脚本中添加应答处理, 需要脚本文件添加needRsp字段
        #         2. print使用logger替代, 保存到本地log.txt
        #         3. 闪退异常也处理到log.txt
        # 2.2.2 # 1. 删除打开端口提示
        #         2. 删除发送处理中的错误提示


    def savelog2Local(self):
        dialog = QFileDialog()
        if dialog.exec():
            filePath = dialog.selectedFiles()[0]
            with open(filePath, "w+", encoding="gbk") as f:
                f.write(self.comWdiget.log.toPlainText())


def handle_exception(excType, excValue, excTraceback):
    # 如果异常是系统退出，则不做处理
    if issubclass(excType, SystemExit):
        sys.__excepthook__(excType, excValue, excTraceback)
        return

    # 获取异常信息字符串
    errorMsg = "".join(traceback.format_exception(excType, excValue, excTraceback))
    logger.critical(errorMsg)

    # 显示异常信息框
    msg_box = QMessageBox()
    msg_box.setIcon(QMessageBox.Critical)
    msg_box.setText("程序崩溃!")
    msg_box.setInformativeText("请联系工作人员")
    msg_box.setWindowTitle("程序崩溃")
    msg_box.exec_()

    sys.exit(1)

if __name__ == '__main__':
    sys.excepthook = handle_exception 

    app = QApplication(sys.argv)
    win = MainWin()
    win.show()
    win.setWindowIcon(QIcon("./ico.png"))
    sys.exit(app.exec_())

# python 3.7.9-win32
# pip install pyqt5 pyserial pyusb pyinstaller reqhests
# pyinstaller .\comTool.py --clean --onefile --noconsole